<html>

  <head>

  </head>

  <body>

    <div>

      <button id="addTask">

        add task
      </button>

      <button id="startTask">

        start loop
      </button>


      <button id="stopTask">

        stop loop
      </button>

      <button id="pauseTask">

        pause loop
      </button>

      <button id="resumeTask">

        resume loop
      </button>
    </div>


  </body>

  <script>

    /**
     * 首先根据需求设计调度任务数据结构，把数据添加到一个对象中，
     * 有属性 key，fn，delay,maxRetry
     * 我们定义了一个TaskScheduler类，它包含了添加任务、启动任务调度器和停止任务，暂定任务，重启任务的方法
     * 其中包含执行任务的runTask 方法 和多次执行的retry方法
     */

const options = {
    key: '注册名称',
    fn: '被调度函数',
    delay: '延迟执行时间',
    maxRetry: '最大重试次数'
}

  class TaskScheduler{

    constructor(){
      this.tasks = [];
      this.status = true // 调度器状态 默认
      this.timer = null; 
    }

    /**
     * 注册进入调度器
     * @param options 注册配置项 {@link options}
     */
     addTask({key,fn,delay,maxRetry}){

      // 开始状态才能添加到数组中
      if(this.status){
        console.log('add success')
        this.tasks.push({
          key,fn,delay,maxRetry,addTime:Date.now()
        })
      }
        
    }

    /**
     * 启动调度器
     */

    start() {
      //如果已经有定时器在运行，则先清除定时器
      if (this.timerId) {
        clearInterval(this.timerId);
      }
      //调用定时器函数，将任务列表作为参数传入
      this.timerId = setInterval(() => {
        this.runTasks(this.tasks);
      }, 1000); //每秒执行一次任务列表中的任务
    }

    //执行任务列表中的任务
    runTasks(tasks) {
      console.log('tasks',tasks)
      //遍历任务列表
      tasks.forEach((task, index) => {

        //如果当前时间大于等于任务的执行时间，说明该任务需要执行
        if (Date.now() >= task.delay+task.addTime) {
          
           //从任务列表中删除已执行的任务
          tasks.splice(index, 1);

          //调用retry 执行函数
         
          this.retry(task.fn,task.maxRetry)
        
        }
      });
    }

    retry(fn, maxRetry){
      // 返回一个promise
      return new Promise(async (resolve, reject) => {
        let retryCount = 0;
        let timer;
       
        const run = async () => {
          try {

            // 执行函数
            const result = await fn();
            // 如果成功返回
            resolve(result);
          } catch (err) {
            // 如果失败重试
            if (retryCount < maxRetry) {
              retryCount++;
              console.log(retryCount)
              //清除定时器
              clearTimeout(timer);

              timer = setTimeout(run, 1000);
            } else {
              reject(err);
            }
          }
        };
        // 立即执行函数
        timer = setTimeout(run, 0);
      });

    }

    /**
     * 停止执行
     */
    stop(){
        clearInterval(this.timerId);
        this.timer = null;
    }

    /**
     * 暂停执行
     */

    pause(){

      clearInterval(this.timerId);
        this.timer = null;
        this.status= false

    }

    /**
     * 重新执行
     */
    resume(){

      this.status = true
      this.start()

    }


  }

  let timeControl = new TaskScheduler();


  var addTask = document.getElementById('addTask')
  addTask.onclick = function(){

    timeControl.addTask({
      key: 'a',
      fn: async()=>{
        const response = await fetch('https://p9s5xa.laf.run/handleFetch');
        if (!response.ok) {
          throw new Error('Failed to fetch data');
        }
        return response.json();

      },
      delay:4000,
      maxRetry:4
    
    })

  }


  var startBtn = document.getElementById('startTask')

  startBtn.onclick= function(){
    timeControl.start()
  }


  var stopBtn = document.getElementById('stopTask')
  stopBtn.onclick = function(){
    timeControl.stop()
  }

  var pauseBtn = document.getElementById('pauseTask')
  pauseBtn.onclick = function(){
    timeControl.pause()
  }


  var resumeBtn = document.getElementById('resumeTask')
  resumeBtn.onclick = function(){
    timeControl.resume()
  }


  </script>
</html>